﻿using PwjCy.Lite.Common;
using PwjCy.Lite.Core;
using PwjCy.Lite.EntityLite;
using PwjCy.Lite.EntityLite.Imp;
using PwjCy.Lite.Storage;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Transactions;

namespace PwjCy.Lite.Persistence.Imp
{
    /// <summary>
    /// 持久层上下文对象
    /// </summary>
    public class PersisterContext
    {
        public PersisterContext()
        {
            PLServices.PersisterMapping.RegisterPersitenceDriver();
        }
        /// <summary>
        /// 保存对象（增删改）
        /// </summary>
        /// <param name="pwjcyObject"></param>
        /// <returns></returns>
        public bool Save(IPwjCyObject pwjcyObject)
        {
            //状态模式，传入数据的对象决定内部使用什么样的方法
            //桥接模式，多维度（库的数量，对象的数量,表的数量）
            //单库（通过StorageAlias的数量来识别）
            //1.单条数据的增删改
            //2.单表的批量增删改（数据库事务，可要可不要）
            //3.单库多表的增删改（主表+分表，主表必写入数据,需要数据库事务）

            //多库
            //1.单条数据主库主表增删改，分库分表增删改
            //2.主库主表批量增删改,分库分表批量增删改
            try
            {
                using (TransactionScope transScope = new TransactionScope())
                {
                    IConnection conn = EntityLiteRelationMap.Instance.Connection(pwjcyObject.StorageAlias);
                    using ((IDbConnection)conn.InnerConnection)
                    {
                        conn.Open();
                        IPreparedStatement stmt = conn.PrepareStatement(EntityLiteRelationMap.Instance.SqlBuilder(pwjcyObject.StorageAlias).SaveSql(pwjcyObject.GetType(), pwjcyObject.TableName, pwjcyObject.ObjectOperateType));
                        stmt.SetParameter(pwjcyObject);
                        int result = stmt.ExecuteNonQuery();
                        stmt.ClearParameter();
                        if (result < 1) { throw new Exception("ExecuteNonQuery Fail:" + stmt.CommandText); }
                    }
                    transScope.Complete();
                    return true;

                }
            }
            catch (Exception ex)
            {
                ServiceHub.LoggerService.Error("Save Object Error", ex);
                throw ex;
            }
        }
        private bool SaveCurrent(IPwjCyObject pwjcyObject)
        {
            IConnection conn = EntityLiteRelationMap.Instance.Connection(pwjcyObject.StorageAlias);
            using ((IDbConnection)conn.InnerConnection)
            {
                conn.Open();
                IPreparedStatement stmt = conn.PrepareStatement(EntityLiteRelationMap.Instance.SqlBuilder(pwjcyObject.StorageAlias).SaveSql(pwjcyObject.GetType(), pwjcyObject.TableName, pwjcyObject.ObjectOperateType));
                stmt.SetParameter(pwjcyObject);
                int result = stmt.ExecuteNonQuery();
                stmt.ClearParameter();
                if (result < 1) { return false; }
            }
            return true;
        }
        private bool SaveCurrentMultiple(IPwjCyObject pwjcyObject)
        {
            IConnection conn = EntityLiteRelationMap.Instance.Connection(pwjcyObject.StorageAlias);
            using ((IDbConnection)conn.InnerConnection)
            {
                conn.Open();
                IDbTransaction tran = conn.BeginTransaction();
                try
                {
                    SaveCurrentMultiple(pwjcyObject, conn, tran);
                    tran.Commit();
                }
                catch (Exception ex)
                {
                    tran.Rollback();
                    return false;
                }
            }
            return true;
        }
        private void SaveCurrentMultiple(IPwjCyObject pwjcyObject, IConnection conn, IDbTransaction tran)
        {
            IPreparedStatement stmt = conn.PrepareStatement(EntityLiteRelationMap.Instance.SqlBuilder(pwjcyObject.StorageAlias).SaveSql(pwjcyObject.GetType(), pwjcyObject.TableName, pwjcyObject.ObjectOperateType));
            stmt.SetParameter(pwjcyObject);
            stmt.Transaction = tran;
            int result = stmt.ExecuteNonQuery();
            stmt.ClearParameter();
            if (result < 1) { throw new Exception(string.Format("保存失败：{0}", pwjcyObject.Id)); }
        }
        public IPwjCyObject LoadPwjCyObject(string storageAlias, Type t, object Id)
        {
            IPwjCyObject pwjcyObject = ServiceHub.Instance.GetService<ITypeService>().CreateInstance(t, storageAlias);
            IConnection conn = EntityLiteRelationMap.Instance.Connection(pwjcyObject.StorageAlias);
            using ((IDbConnection)conn.InnerConnection)
            {
                conn.Open();
                IPreparedStatement stmt = conn.PrepareStatement(EntityLiteRelationMap.Instance.SqlBuilder(pwjcyObject.StorageAlias).LoadPwjCyObjectSql(pwjcyObject.GetType(), pwjcyObject.TableName));
                stmt.SetParameter("Id", Id);
                DataSet ds = stmt.ExecuteDataSet();
                stmt.ClearParameter();
                if (null == ds || null == ds.Tables[0].Rows || ds.Tables[0].Rows.Count == 0) return null;
                pwjcyObject = (IPwjCyObject)ListHelper.DataRow2PwjCyObject(ds.Tables[0].Rows[0], t);
                ((PwjCyObject)pwjcyObject).GetPwjCyObject(Id);
                return pwjcyObject;
            }
        }
    }
}
